
package com.kanjian.music.download;

import java.util.ArrayList;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;
import java.util.concurrent.PriorityBlockingQueue;
import java.util.concurrent.RunnableFuture;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import com.kanjian.music.entity.Music;

/**
 * 线程池批量下载音乐工具类
 * 
 * @author xuyanjun
 */
public class DownloadManager {

    private static PriorityExecutor mExecutor = (PriorityExecutor) PriorityExecutor
            .newFixedThreadPool(1);

    
    // 边听边存 因为马上要让用户听到 所以需要与普通下载队列区分
    private static PriorityExecutor mUrgentExecutor = (PriorityExecutor) PriorityExecutor
            .newFixedThreadPool(2);

    private DownloadManager() {
    }

    public static void addTask(MusicDownloadTask task) {
        mExecutor.submit(task, task.mPriority);
    }

    public static void addTaskList(ArrayList<MusicDownloadTask> taskList) {
        for (MusicDownloadTask task : taskList) {
            mExecutor.submit(task, task.mPriority);
        }
    }

    public static void addUrgentTask(MusicDownloadTask task) {
        mUrgentExecutor.submit(task, task.mPriority);
    }

    static class PriorityExecutor extends ThreadPoolExecutor {

        private static PriorityBlockingQueue<Runnable> mQueue = new PriorityBlockingQueue<Runnable>();

        public PriorityExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime,
                TimeUnit unit, BlockingQueue<Runnable> workQueue) {
            super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
        }

        public static ExecutorService newFixedThreadPool(int nThreads) {
            return new PriorityExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, mQueue);
        }

        public Future<?> submit(Runnable task, int priority) {
            System.out.println("queueSize: " + mQueue.size());
            return super.submit(new ComparableFutureTask(task, null, priority));
        }

        public void execute(Runnable command, int priority) {
            super.execute(new ComparableFutureTask(command, null, priority));
        }

        @Override
        protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) {
            return (RunnableFuture<T>) callable;
        }

        @Override
        protected <T> RunnableFuture<T> newTaskFor(Runnable runnable, T value) {
            return (RunnableFuture<T>) runnable;
        }
    }

    static class ComparableFutureTask<T> extends FutureTask<T> implements
            Comparable<ComparableFutureTask<T>> {

        volatile int priority = 0;

        public Runnable mRunnable;

        public ComparableFutureTask(Runnable runnable, T result, int priority) {
            super(runnable, result);
            mRunnable = runnable;
            this.priority = priority;
        }

        public ComparableFutureTask(Callable<T> callable, int priority) {
            super(callable);
            this.priority = priority;
        }

        @Override
        public int compareTo(ComparableFutureTask<T> o) {
            return o.priority < priority ? -1 : (o.priority == priority ? 0 : 1);
        }
    }

    public static MusicDownloadTask getDownloadTaskByMusicId(long musicId) {
        for (Runnable task : mExecutor.getQueue()) {
            if (task instanceof ComparableFutureTask) {
                if (((ComparableFutureTask) task).mRunnable instanceof MusicDownloadTask) {
                    if (((MusicDownloadTask) ((ComparableFutureTask) task).mRunnable).mMusic
                            .getMusicId() == musicId) {
                        return ((MusicDownloadTask) ((ComparableFutureTask) task).mRunnable);
                    }
                }
            }
        }
        return null;
    }
}
